//
//  IMNetworkUtils.m
//  DualMediationSDK
//
//  Created by YeJary on 2025/6/23.
//

#import "IMNetworkUtils.h"
#import "../Logger/IMLogUtils.h"
#import "../JSON/IMJSONUtils.h"
#import "../Encryption/IMEncryptUtils.h"
#import "IMAPIConfig.h"
#import "../../API/TA/DMThinkingManager.h"
#import <AFNetworking/AFURLSessionManager.h>
#import <AFNetworking/AFHTTPSessionManager.h>
#import <AFNetworking/AFURLRequestSerialization.h>
#import <AFNetworking/AFURLResponseSerialization.h>
#import <AFNetworking/AFNetworkReachabilityManager.h>
#import <CommonCrypto/CommonCrypto.h>


#pragma mark - IMNetworkConfig Implementation

@implementation IMNetworkConfig

+ (instancetype)defaultConfig {
    IMNetworkConfig *config = [[IMNetworkConfig alloc] init];
    config.baseURL = @"";
    config.timeoutInterval = 30.0;
    config.defaultHeaders = @{}; // 移除默认请求头，在sessionManager中统一设置
    config.enableLogging = YES;
    config.enableRetry = YES;
    config.maxRetryCount = 3;
    config.retryInterval = 2.0;
    config.acceptableContentTypes = @[@"application/json", @"text/json", @"text/javascript", @"text/html",@"text/plain"];
    return config;
}

+ (instancetype)debugConfig {
    IMNetworkConfig *config = [self defaultConfig];
    config.enableLogging = YES;
    config.timeoutInterval = 60.0;
    return config;
}

+ (instancetype)releaseConfig {
    IMNetworkConfig *config = [self defaultConfig];
    config.enableLogging = NO;
    config.timeoutInterval = 15.0;
    return config;
}

@end

#pragma mark - IMNetworkResponse Implementation

@interface IMNetworkResponse ()
@property (nonatomic, strong, readwrite) id data;
@property (nonatomic, assign, readwrite) NSInteger statusCode;
@property (nonatomic, strong, readwrite) NSDictionary *headers;
@property (nonatomic, strong, readwrite) NSError *error;
@property (nonatomic, assign, readwrite) NSTimeInterval duration;
@property (nonatomic, strong, readwrite) NSString *requestID;
@end

@implementation IMNetworkResponse

- (instancetype)initWithData:(id)data 
                  statusCode:(NSInteger)statusCode 
                     headers:(NSDictionary *)headers 
                       error:(NSError *)error 
                    duration:(NSTimeInterval)duration 
                   requestID:(NSString *)requestID {
    self = [super init];
    if (self) {
        _data = data;
        _statusCode = statusCode;
        _headers = headers;
        _error = error;
        _duration = duration;
        _requestID = requestID;
    }
    return self;
}

@end

#pragma mark - IMNetworkTask Implementation

@interface IMNetworkTask ()
@property (nonatomic, strong, readwrite) NSString *taskID;
@property (nonatomic, assign, readwrite) BOOL isExecuting;
@property (nonatomic, assign, readwrite) BOOL isCancelled;
@property (nonatomic, strong) NSURLSessionTask *dataTask;
@end

@implementation IMNetworkTask

- (instancetype)initWithDataTask:(NSURLSessionTask *)dataTask taskID:(NSString *)taskID {
    self = [super init];
    if (self) {
        _dataTask = dataTask;
        _taskID = taskID;
        _isExecuting = dataTask.state == NSURLSessionTaskStateRunning;
        _isCancelled = NO;
    }
    return self;
}

- (void)cancel {
    if (!self.isCancelled && self.dataTask) {
        [self.dataTask cancel];
        _isCancelled = YES;
        _isExecuting = NO;
    }
}

@end

#pragma mark - IMNetworkUtils Implementation

@interface IMNetworkUtils ()
@property (nonatomic, strong) AFHTTPSessionManager *sessionManager;
@property (nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
@property (nonatomic, strong) IMNetworkConfig *config;
@property (nonatomic, strong) NSMutableDictionary<NSString *, IMNetworkTask *> *activeTasks;
@property (nonatomic, strong) NSMutableDictionary *networkStatistics;
@end

@implementation IMNetworkUtils

static IMNetworkUtils *_sharedInstance = nil;
static dispatch_once_t _onceToken;

+ (instancetype)sharedInstance {
    dispatch_once(&_onceToken, ^{
        _sharedInstance = [[IMNetworkUtils alloc] init];
    });
    return _sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _activeTasks = [NSMutableDictionary dictionary];
        _networkStatistics = [NSMutableDictionary dictionaryWithDictionary:@{
            @"totalRequests": @0,
            @"successfulRequests": @0,
            @"failedRequests": @0,
            @"totalBytes": @0,
            @"averageResponseTime": @0
        }];
    }
    return self;
}

+ (void)initialize {
    [self initWithConfig:[IMNetworkConfig defaultConfig]];
}

+ (void)initWithConfig:(IMNetworkConfig *)config {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    instance.config = config ?: [IMNetworkConfig defaultConfig];
    
    // 创建会话配置
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfig.timeoutIntervalForRequest = config.timeoutInterval;
    
    // 初始化会话管理器，设置baseURL
    NSURL *baseURL = nil;
    if (config.baseURL && config.baseURL.length > 0) {
        baseURL = [NSURL URLWithString:config.baseURL];
    }
    instance.sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL sessionConfiguration:sessionConfig];
    
    // 设置响应序列化器
    instance.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];
    instance.sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:config.acceptableContentTypes];
    
    // 设置请求序列化器
    instance.sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
    
    // 简化的请求头设置
     [instance.sessionManager.requestSerializer setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    
    instance.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
    
    [IMLogUtils info:IMLogTagNetwork format:@"[NetworkUtils] 网络工具初始化完成，baseURL: %@", config.baseURL];
}

+ (IMNetworkConfig *)currentConfig {
    return [IMNetworkUtils sharedInstance].config;
}

+ (void)updateConfig:(IMNetworkConfig *)config {
    [self initWithConfig:config];
}

+ (IMNetworkTask *)GET:(NSString *)URLString parameters:(id)parameters success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    return [self request:IMNetworkMethodGET URLString:URLString parameters:parameters headers:nil success:success failure:failure];
}

+ (IMNetworkTask *)POST:(NSString *)URLString parameters:(id)parameters success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    return [self request:IMNetworkMethodPOST URLString:URLString parameters:parameters headers:nil success:success failure:failure];
}

+ (IMNetworkTask *)PUT:(NSString *)URLString parameters:(id)parameters success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    return [self request:IMNetworkMethodPUT URLString:URLString parameters:parameters headers:nil success:success failure:failure];
}

+ (IMNetworkTask *)DELETE:(NSString *)URLString parameters:(id)parameters success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    return [self request:IMNetworkMethodDELETE URLString:URLString parameters:parameters headers:nil success:success failure:failure];
}

+ (IMNetworkTask *)postPaymentRequest:(NSString *)URLString parameters:(id)parameters success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    NSString *requestID = [[NSUUID UUID] UUIDString];
    NSDate *startTime = [NSDate date];
    
    // 构建完整的请求URL
    NSString *baseURLString = instance.sessionManager.baseURL ? instance.sessionManager.baseURL.absoluteString : @"";
    NSString *fullURL = URLString;
    
    if (instance.config.enableLogging) {
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 支付请求开始 - POST %@, ID: %@", URLString, requestID];
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 完整请求URL: %@", fullURL];
        
        if (parameters) {
            NSString *parametersString = [IMJSONUtils jsonStringFromObject:parameters];
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 请求参数: %@", parametersString ?: @"参数序列化失败"];
        }
    }
    
    // 1. 转 JSON 字符串
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    
    // 2. 加密 JSON 字符串
    NSString *cipher = [IMEncryptUtils aesEncryptToBase64:jsonString 
                                                      key:@"ryjtmvrlxxqwnwpb" 
                                                       iv:@"ped5j50msr5yulcl"];
    
    if (!cipher) {
        if (instance.config.enableLogging) {
            [IMLogUtils error:IMLogTagError format:@"[NetworkUtils] 支付请求加密失败 - %@, ID: %@", URLString, requestID];
        }
        
        if (failure) {
            NSError *err = [NSError errorWithDomain:@"DMNetworkErrorDomain" 
                                               code:-10003 
                                           userInfo:@{NSLocalizedDescriptionKey: @"加密失败"}];
            
            // 上报SDK_HTTP_ERROR事件
            NSString *interfacePath = @"payment_encrypt_error";
            NSString *httpCode = @"0";
            NSString *httpMsg = @"加密失败";
            
            NSDictionary *eventProperties = @{
                @"w_interface_path": interfacePath,
                @"w_http_code": httpCode,
                @"w_http_msg": httpMsg
            };
            
            [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_HTTP_ERROR" properties:eventProperties];
            
            NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startTime];
            IMNetworkResponse *response = [[IMNetworkResponse alloc] initWithData:nil
                                                                       statusCode:0
                                                                          headers:nil
                                                                            error:err
                                                                         duration:duration
                                                                        requestID:requestID];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                failure(response);
            });
        }
        return nil;
    }
    
    // 3. 构造原始 POST 请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:fullURL]];
    request.HTTPMethod = @"POST";
    request.timeoutInterval = 15;
    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
    request.HTTPBody = [cipher dataUsingEncoding:NSUTF8StringEncoding];
    
    if (instance.config.enableLogging) {
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 支付请求加密完成，Content-Type: text/plain"];
    }
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request 
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startTime];
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        
        if (error) {
            if (instance.config.enableLogging) {
                [IMLogUtils error:IMLogTagError format:@"[NetworkUtils] 支付请求失败 - %@, 错误: %@, 耗时: %.3fs, ID: %@", 
                      URLString, error.localizedDescription, duration, requestID];
            }
            
            // 上报SDK_HTTP_ERROR事件
            NSString *interfacePath = request.URL.path ?: request.URL.absoluteString ?: @"unknown";
            NSString *httpCode = [NSString stringWithFormat:@"%ld", (long)httpResponse.statusCode];
            NSString *httpMsg = error.localizedDescription ?: @"unknown error";
            
            NSDictionary *eventProperties = @{
                @"w_interface_path": interfacePath,
                @"w_http_code": httpCode,
                @"w_http_msg": httpMsg
            };
            
            [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_HTTP_ERROR" properties:eventProperties];
            
            IMNetworkResponse *networkResponse = [[IMNetworkResponse alloc] initWithData:nil
                                                                               statusCode:httpResponse.statusCode
                                                                                  headers:httpResponse.allHeaderFields
                                                                                    error:error
                                                                                 duration:duration
                                                                                requestID:requestID];
            
            @synchronized (instance.activeTasks) {
                [instance.activeTasks removeObjectForKey:requestID];
            }
            
            if (failure) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    failure(networkResponse);
                });
            }
        } else {
            id json = nil;
            if (data) {
                json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            }
            
            if (instance.config.enableLogging) {
                [IMLogUtils info:IMLogTagNetwork format:@"[NetworkUtils] 支付请求成功 - %@, 状态码: %ld, 耗时: %.3fs, ID: %@", 
                      URLString, (long)httpResponse.statusCode, duration, requestID];
                
                if (json) {
                    NSString *responseString = [IMJSONUtils jsonStringFromObject:json];
                    [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 支付响应数据: %@", responseString ?: @"响应数据序列化失败"];
                }
            }
            
            IMNetworkResponse *networkResponse = [[IMNetworkResponse alloc] initWithData:json
                                                                               statusCode:httpResponse.statusCode
                                                                                  headers:httpResponse.allHeaderFields
                                                                                    error:nil
                                                                                 duration:duration
                                                                                requestID:requestID];
            
            @synchronized (instance.activeTasks) {
                [instance.activeTasks removeObjectForKey:requestID];
            }
            
            if (success) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    success(networkResponse);
                });
            }
        }
    }];
    
    [task resume];
    
    IMNetworkTask *networkTask = [[IMNetworkTask alloc] initWithDataTask:task taskID:requestID];
    
    @synchronized (instance.activeTasks) {
        instance.activeTasks[requestID] = networkTask;
    }
    
    return networkTask;
}

+ (IMNetworkTask *)request:(IMNetworkMethod)method URLString:(NSString *)URLString parameters:(id)parameters headers:(NSDictionary *)headers success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    NSString *requestID = [[NSUUID UUID] UUIDString];
    // 始终构建完整URL
    NSString *baseURLString = instance.sessionManager.baseURL ? instance.sessionManager.baseURL.absoluteString : @"";
    NSString *fullURLString = [baseURLString stringByAppendingString:URLString];

    if (instance.config.enableLogging) {
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 请求开始 - %@ %@, ID: %@", [self methodStringFromEnum:method], URLString, requestID];
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 完整请求URL: %@", fullURLString.length > 0 ? fullURLString : URLString];
        if (parameters) {
            NSString *parametersString = [IMJSONUtils jsonStringFromObject:parameters];
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 请求参数: %@", parametersString ?: @"参数序列化失败"];
        } else {
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 请求参数: 无参数"];
        }
        NSDictionary *defaultHeaders = instance.sessionManager.requestSerializer.HTTPRequestHeaders;
        if (defaultHeaders && defaultHeaders.count > 0) {
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 默认请求头: %@", defaultHeaders];
        }
        if (headers && headers.count > 0) {
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 额外请求头: %@", headers];
        }
    }

    __block NSInteger attempt = 0;
    NSTimeInterval baseInterval = instance.config.retryInterval;
    if (baseInterval < 0.5) { baseInterval = 0.5; }
    IMNetworkTask *networkTask = [[IMNetworkTask alloc] initWithDataTask:nil taskID:requestID];
    NSString *requestMethodString = [self methodStringFromEnum:method];
    NSString *requestURLForLog = fullURLString.length > 0 ? fullURLString : URLString;

    __block void (^performRequest)(void) = nil;
    performRequest = ^{
        NSDate *startTime = [NSDate date];
        NSURLSessionDataTask *dataTask = nil;
        switch (method) {
            case IMNetworkMethodGET: {
                dataTask = [instance.sessionManager GET:fullURLString parameters:parameters headers:headers progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                    [self handleSuccess:task responseObject:responseObject startTime:startTime requestID:requestID success:success];
                } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
                    NSInteger statusCode = httpResponse.statusCode;
                    BOOL canRetry = instance.config.enableRetry && [self shouldRetryWithError:error statusCode:statusCode] && attempt < instance.config.maxRetryCount;
                    if (canRetry) {
                        attempt++;
                        NSTimeInterval delay = [self retryDelayForAttempt:attempt baseInterval:baseInterval];
                        if (instance.config.enableLogging) {
                            [IMLogUtils warning:IMLogTagNetwork format:@"[NetworkUtils] 请求失败，准备重试(%ld/%ld)，延迟: %.2fs - %@ %@", (long)attempt, (long)instance.config.maxRetryCount, delay, requestMethodString, requestURLForLog];
                        }
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                            if (performRequest) {
                                performRequest();
                            }
                        });
                        return;
                    }
                    [self handleFailure:task error:error startTime:startTime requestID:requestID httpMethod:requestMethodString URLString:requestURLForLog failure:failure];
                }];
                break;
            }
            case IMNetworkMethodPOST: {
                dataTask = [instance.sessionManager POST:fullURLString parameters:parameters headers:headers progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                    [self handleSuccess:task responseObject:responseObject startTime:startTime requestID:requestID success:success];
                } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
                    NSInteger statusCode = httpResponse.statusCode;
                    BOOL canRetry = instance.config.enableRetry && [self shouldRetryWithError:error statusCode:statusCode] && attempt < instance.config.maxRetryCount;
                    if (canRetry) {
                        attempt++;
                        NSTimeInterval delay = [self retryDelayForAttempt:attempt baseInterval:baseInterval];
                        if (instance.config.enableLogging) {
                            [IMLogUtils warning:IMLogTagNetwork format:@"[NetworkUtils] 请求失败，准备重试(%ld/%ld)，延迟: %.2fs - %@ %@", (long)attempt, (long)instance.config.maxRetryCount, delay, requestMethodString, requestURLForLog];
                        }
                        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                            if (performRequest) {
                                performRequest();
                            }
                        });
                        return;
                    }
                    [self handleFailure:task error:error startTime:startTime requestID:requestID httpMethod:requestMethodString URLString:requestURLForLog failure:failure];
                }];
                break;
            }
            default: {
                [IMLogUtils error:IMLogTagError format:@"[NetworkUtils] 不支持的请求方法: %ld", (long)method];
                return;
            }
        }

        networkTask.dataTask = dataTask;
        @synchronized (instance.activeTasks) {
            instance.activeTasks[requestID] = networkTask;
        }
    };

    performRequest();
    return networkTask;
}

+ (NSString *)networkStatus {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    AFNetworkReachabilityStatus status = instance.reachabilityManager.networkReachabilityStatus;
    
    switch (status) {
        case AFNetworkReachabilityStatusUnknown: return @"Unknown";
        case AFNetworkReachabilityStatusNotReachable: return @"NotReachable";
        case AFNetworkReachabilityStatusReachableViaWWAN: return @"ReachableViaWWAN";
        case AFNetworkReachabilityStatusReachableViaWiFi: return @"ReachableViaWiFi";
        default: return @"Unknown";
    }
}

+ (BOOL)isNetworkReachable {
    return [IMNetworkUtils sharedInstance].reachabilityManager.reachable;
}

+ (BOOL)isWiFiNetwork {
    return [IMNetworkUtils sharedInstance].reachabilityManager.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi;
}

+ (void)startNetworkMonitoring:(void(^)(NSString *status))callback {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    
    [instance.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        NSString *statusString = [self networkStatus];
        [IMLogUtils info:IMLogTagNetwork format:@"[NetworkUtils] 网络状态变化: %@", statusString];
        
        if (callback) {
            callback(statusString);
        }
    }];
    
    [instance.reachabilityManager startMonitoring];
}

+ (void)stopNetworkMonitoring {
    [[IMNetworkUtils sharedInstance].reachabilityManager stopMonitoring];
}

+ (void)cancelAllRequests {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    
    @synchronized (instance.activeTasks) {
        for (IMNetworkTask *task in instance.activeTasks.allValues) {
            [task cancel];
        }
        [instance.activeTasks removeAllObjects];
    }
    
    [IMLogUtils info:IMLogTagNetwork format:@"[NetworkUtils] 已取消所有网络请求"];
}

+ (NSInteger)activeRequestCount {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    @synchronized (instance.activeTasks) {
        return instance.activeTasks.count;
    }
}

+ (void)cancelRequestsWithURL:(NSString *)URLString {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    
    @synchronized (instance.activeTasks) {
        NSMutableArray *tasksToCancel = [NSMutableArray array];
        
        for (NSString *taskID in instance.activeTasks) {
            IMNetworkTask *task = instance.activeTasks[taskID];
            if ([task.dataTask.currentRequest.URL.absoluteString containsString:URLString]) {
                [tasksToCancel addObject:taskID];
                [task cancel];
            }
        }
        
        for (NSString *taskID in tasksToCancel) {
            [instance.activeTasks removeObjectForKey:taskID];
        }
    }
    
    [IMLogUtils info:IMLogTagNetwork format:@"[NetworkUtils] 已取消URL包含 %@ 的网络请求", URLString];
}

#pragma mark - 文件操作

+ (IMNetworkTask *)uploadFile:(NSString *)URLString parameters:(id)parameters fileData:(NSData *)fileData name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType progress:(IMNetworkProgressBlock)progress success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    NSString *requestID = [[NSUUID UUID] UUIDString];
    NSDate *startTime = [NSDate date];
    
    if (instance.config.enableLogging) {
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 文件上传开始 - %@, 文件名: %@, ID: %@", URLString, fileName, requestID];
    }
    
    NSURLSessionDataTask *uploadTask = [instance.sessionManager POST:URLString parameters:parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:fileData name:name fileName:fileName mimeType:mimeType];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
         if (progress) {
             progress(uploadProgress.fractionCompleted);
         }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [self handleSuccess:task responseObject:responseObject startTime:startTime requestID:requestID success:success];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [self handleFailure:task error:error startTime:startTime requestID:requestID httpMethod:@"POST" URLString:URLString failure:failure];
    }];
    
    IMNetworkTask *networkTask = [[IMNetworkTask alloc] initWithDataTask:uploadTask taskID:requestID];
    
    @synchronized (instance.activeTasks) {
        instance.activeTasks[requestID] = networkTask;
    }
    
    return networkTask;
}

+ (IMNetworkTask *)downloadFile:(NSString *)URLString destination:(NSString *)destination progress:(IMNetworkProgressBlock)progress success:(IMNetworkSuccessBlock)success failure:(IMNetworkFailureBlock)failure {
    
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    NSString *requestID = [[NSUUID UUID] UUIDString];
    NSDate *startTime = [NSDate date];
    
    if (instance.config.enableLogging) {
        [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 文件下载开始 - %@, 目标路径: %@, ID: %@", URLString, destination, requestID];
    }
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URLString]];
    
    NSURLSessionDownloadTask *downloadTask = [instance.sessionManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
         if (progress) {
             progress(downloadProgress.fractionCompleted);
         }
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        return [NSURL fileURLWithPath:destination];
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        if (error) {
            NSString *methodString = request.HTTPMethod.length > 0 ? request.HTTPMethod : @"GET";
            NSString *urlStringForLog = request.URL.absoluteString.length > 0 ? request.URL.absoluteString : URLString;
            [self handleFailure:nil error:error startTime:startTime requestID:requestID httpMethod:methodString URLString:urlStringForLog failure:failure];
        } else {
            [self handleSuccess:nil responseObject:@{@"filePath": filePath.path} startTime:startTime requestID:requestID success:success];
        }
    }];
    
    [downloadTask resume];
    
    IMNetworkTask *networkTask = [[IMNetworkTask alloc] initWithDataTask:downloadTask taskID:requestID];
    
    @synchronized (instance.activeTasks) {
        instance.activeTasks[requestID] = networkTask;
    }
    
    return networkTask;
}

+ (NSDictionary *)networkStatistics {
    return [[IMNetworkUtils sharedInstance].networkStatistics copy];
}

+ (void)setCachePolicy:(NSURLRequestCachePolicy)policy {
    [IMNetworkUtils sharedInstance].sessionManager.requestSerializer.cachePolicy = policy;
}

+ (void)clearCache {
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
}

+ (NSString *)cacheSize {
    NSURLCache *cache = [NSURLCache sharedURLCache];
    NSUInteger bytes = cache.currentDiskUsage;
    return [NSByteCountFormatter stringFromByteCount:bytes countStyle:NSByteCountFormatterCountStyleFile];
}

+ (NSString *)methodStringFromEnum:(IMNetworkMethod)method {
    switch (method) {
        case IMNetworkMethodGET: return @"GET";
        case IMNetworkMethodPOST: return @"POST";
        case IMNetworkMethodPUT: return @"PUT";
        case IMNetworkMethodDELETE: return @"DELETE";
        default: return @"UNKNOWN";
    }
}

+ (void)handleSuccess:(NSURLSessionDataTask *)task responseObject:(id)responseObject startTime:(NSDate *)startTime requestID:(NSString *)requestID success:(IMNetworkSuccessBlock)success {
    NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startTime];
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
    
    IMNetworkResponse *response = [[IMNetworkResponse alloc] initWithData:responseObject
                                                               statusCode:httpResponse.statusCode
                                                                  headers:httpResponse.allHeaderFields
                                                                    error:nil
                                                                 duration:duration
                                                                requestID:requestID];
    
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    if (instance.config.enableLogging) {
        [IMLogUtils info:IMLogTagNetwork format:@"[NetworkUtils] 请求成功 - %@ %@, 状态码: %ld, 耗时: %.3fs, ID: %@", 
              task.currentRequest.HTTPMethod, task.currentRequest.URL.absoluteString, 
              (long)httpResponse.statusCode, duration, requestID];
        
        // 输出响应头
        if (httpResponse.allHeaderFields && httpResponse.allHeaderFields.count > 0) {
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 响应头: %@", httpResponse.allHeaderFields];
        }
        
        // 输出响应数据
        if (responseObject) {
            NSString *responseString = [IMJSONUtils jsonStringFromObject:responseObject];
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 响应数据: %@", responseString ?: @"响应数据序列化失败"];
        } else {
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 响应数据: 无数据"];
        }
    }
    
    @synchronized (instance.activeTasks) {
        [instance.activeTasks removeObjectForKey:requestID];
    }
    
    if (success) {
        dispatch_async(dispatch_get_main_queue(), ^{
            success(response);
        });
    }
}

+ (void)handleFailure:(NSURLSessionDataTask *)task error:(NSError *)error startTime:(NSDate *)startTime requestID:(NSString *)requestID httpMethod:(NSString *)httpMethod URLString:(NSString *)URLString failure:(IMNetworkFailureBlock)failure {
    NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startTime];
    NSHTTPURLResponse *httpResponse = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey];
    if (!httpResponse && task) {
        httpResponse = (NSHTTPURLResponse *)task.response;
    }
    
    NSInteger statusCode = httpResponse ? httpResponse.statusCode : 0;
    NSDictionary *responseHeaders = httpResponse.allHeaderFields;
    
    IMNetworkResponse *response = [[IMNetworkResponse alloc] initWithData:nil
                                                               statusCode:statusCode
                                                                  headers:responseHeaders
                                                                    error:error
                                                                 duration:duration
                                                                requestID:requestID];
    
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    NSString *resolvedMethod = httpMethod.length > 0 ? httpMethod : @"UNKNOWN";
    NSString *resolvedURL = URLString.length > 0 ? URLString : @"unknown";
    id failingURL = error.userInfo[NSURLErrorFailingURLStringErrorKey];
    if ([failingURL isKindOfClass:[NSString class]] && ((NSString *)failingURL).length > 0) {
        resolvedURL = (NSString *)failingURL;
    } else if (httpResponse.URL) {
        NSString *absoluteURL = httpResponse.URL.absoluteString;
        if (absoluteURL.length > 0) {
            resolvedURL = absoluteURL;
        }
    }
    
    if (instance.config.enableLogging) {
        NSString *errorMessage = error.localizedDescription ?: @"unknown error";
        [IMLogUtils error:IMLogTagError format:@"[NetworkUtils] 请求失败 - %@ %@, 错误: %@, 耗时: %.3fs, ID: %@", 
              resolvedMethod, resolvedURL, errorMessage, duration, requestID];
        
        if (error.userInfo && error.userInfo.count > 0) {
            [IMLogUtils error:IMLogTagError format:@"[NetworkUtils] 错误详情: %@", error.userInfo];
        }
        
        if (responseHeaders && responseHeaders.count > 0) {
            [IMLogUtils debug:IMLogTagNetwork format:@"[NetworkUtils] 失败响应头: %@", responseHeaders];
        }
        
        NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
        if (errorData.length > 0) {
            NSString *errorString = [[NSString alloc] initWithData:errorData encoding:NSUTF8StringEncoding];
            if (errorString.length > 0) {
                [IMLogUtils error:IMLogTagError format:@"[NetworkUtils] 错误响应数据: %@", errorString];
            }
        }
    }
    
    NSString *interfacePath = resolvedURL;
    if (httpResponse.URL && httpResponse.URL.path.length > 0) {
        interfacePath = httpResponse.URL.path;
    }
    NSString *httpCode = [NSString stringWithFormat:@"%ld", (long)statusCode];
    NSString *httpMsg = error.localizedDescription ?: @"unknown error";
    
    NSDictionary *eventProperties = @{
        @"w_interface_path": interfacePath ?: @"unknown",
        @"w_http_code": httpCode,
        @"w_http_msg": httpMsg
    };
    
    [[DMThinkingManager sharedManager] thinkingTrackEventWithKey:@"SDK_HTTP_ERROR" properties:eventProperties];
    
    @synchronized (instance.activeTasks) {
        [instance.activeTasks removeObjectForKey:requestID];
    }
    
    if (failure) {
        dispatch_async(dispatch_get_main_queue(), ^{
            failure(response);
        });
    }
}

#pragma mark - SSL配置

+ (void)setSSLValidation:(BOOL)allowInvalidCertificates validatesDomainName:(BOOL)validatesDomainName {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    if (instance.sessionManager) {
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        securityPolicy.allowInvalidCertificates = allowInvalidCertificates;
        securityPolicy.validatesDomainName = validatesDomainName;
        instance.sessionManager.securityPolicy = securityPolicy;
        
        if (instance.config.enableLogging) {
            [IMLogUtils info:IMLogTagNetwork format:@"[IMNetworkUtils] SSL validation configured - allowInvalidCertificates: %@, validatesDomainName: %@", 
                               allowInvalidCertificates ? @"YES" : @"NO", 
                               validatesDomainName ? @"YES" : @"NO"];
        }
    }
}

+ (void)addSSLCertificate:(NSData *)certificateData {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    if (instance.sessionManager && certificateData) {
        AFSecurityPolicy *securityPolicy = instance.sessionManager.securityPolicy;
        if (!securityPolicy) {
            securityPolicy = [AFSecurityPolicy defaultPolicy];
        }
        
        NSMutableSet *certificates = [NSMutableSet setWithSet:securityPolicy.pinnedCertificates];
        [certificates addObject:certificateData];
        securityPolicy.pinnedCertificates = certificates;
        instance.sessionManager.securityPolicy = securityPolicy;
        
        if (instance.config.enableLogging) {
            [IMLogUtils info:IMLogTagNetwork format:@"[IMNetworkUtils] SSL certificate added, total certificates: %lu", (unsigned long)certificates.count];
        }
    }
}

#pragma mark - 调试工具

+ (void)setVerboseLogging:(BOOL)enabled {
    IMNetworkUtils *instance = [IMNetworkUtils sharedInstance];
    instance.config.enableLogging = enabled;
    
    [IMLogUtils info:IMLogTagNetwork format:@"[IMNetworkUtils] Verbose logging %@", enabled ? @"enabled" : @"disabled"];
}

+ (BOOL)exportNetworkLogs:(NSString *)filePath {
    if (!filePath || filePath.length == 0) {
        [IMLogUtils error:IMLogTagError format:@"[IMNetworkUtils] Export failed: invalid file path"];
        return NO;
    }
    
    // 这里可以实现日志导出逻辑
    // 目前返回成功，实际项目中可以根据需要实现具体的日志导出功能
    [IMLogUtils info:IMLogTagNetwork format:@"[IMNetworkUtils] Network logs exported to: %@", filePath];
    return YES;
}


+ (NSString *)signParameters:(NSDictionary *)params withKey:(NSString *)secretKey {
    // 1. 排序
    NSArray *sortedKeys = [[params allKeys] sortedArrayUsingSelector:@selector(compare:)];
    NSMutableArray *paramPairs = [NSMutableArray array];

    for (NSString *key in sortedKeys) {
        id value = params[key];
        if ([value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]]) {
            [paramPairs addObject:[NSString stringWithFormat:@"%@=%@", key, value]];
        }
    }

    // 2. 拼接字符串
    NSString *joinedString = [paramPairs componentsJoinedByString:@"&"];
    // 3. 拼接秘钥（如果服务端有要求）
    NSString *stringToSign = [NSString stringWithFormat:@"%@%@", joinedString, secretKey];
    
    // 4. MD5 加密
    return [self md5:stringToSign];
}

+ (NSDictionary *)signedParametersFrom:(NSDictionary *)params withKey:(NSString *)secretKey {
    NSMutableDictionary *signedParams = [params mutableCopy];
    NSString *sign = [self signParameters:params withKey:secretKey];
    signedParams[@"sign"] = sign;
    return signedParams;
}

+ (NSString *)md5:(NSString *)string {
    const char *str = [string UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (CC_LONG)strlen(str), result);

    NSMutableString *md5 = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [md5 appendFormat:@"%02x", result[i]];
    }
    return md5;
}

// Retry decision helper: determines whether a request should be retried
+ (BOOL)shouldRetryWithError:(NSError *)error statusCode:(NSInteger)statusCode {
    // Do not retry cancelled requests
    if (error && error.code == NSURLErrorCancelled) {
        return NO;
    }

    // Transient network errors (timeouts, connection issues)
    if (error && [error.domain isEqualToString:NSURLErrorDomain]) {
        switch (error.code) {
            case NSURLErrorTimedOut:
            case NSURLErrorCannotFindHost:
            case NSURLErrorCannotConnectToHost:
            case NSURLErrorNetworkConnectionLost:
            case NSURLErrorDNSLookupFailed:
            case NSURLErrorNotConnectedToInternet:
            case NSURLErrorDataNotAllowed:
                return YES;
            default:
                break;
        }
    }

    // HTTP status-based retry policy
    if (statusCode >= 500 && statusCode < 600) {
        return YES; // server errors
    }
    if (statusCode == 429 || statusCode == 408) {
        return YES; // too many requests or timeout
    }
    if (statusCode == 0) {
        // No response code (e.g., network error without HTTP response)
        return YES;
    }

    return NO;
}

// Exponential backoff with jitter for retry delay calculation
+ (NSTimeInterval)retryDelayForAttempt:(NSInteger)attempt baseInterval:(NSTimeInterval)baseInterval {
    if (attempt < 1) attempt = 1;
    if (baseInterval < 0.1) baseInterval = 0.1;

    double backoff = baseInterval * pow(2.0, (double)(attempt - 1));

    // Apply jitter to reduce thundering herd: 0.8x - 1.3x
    double r = (double)arc4random() / (double)UINT32_MAX; // [0,1)
    double jitter = 0.8 + (1.3 - 0.8) * r;
    double delay = backoff * jitter;

    // Cap maximum delay to 80s (consistent with other managers)
    double maxDelay = 80.0;
    return MIN(delay, maxDelay);
}


@end
